#pragma once
#include <iostream>
#include <ringbuffer.h>
#include <chrono>
#include <log.h>
extern "C"
{
#include "libavdevice/avdevice.h"
#include "libavcodec/avcodec.h"
#include "libswscale/swscale.h"
#include "libswresample/swresample.h"
#include "libavutil/imgutils.h"
#include <libavutil/timestamp.h>
}
namespace Media
{

	class PacketInfo {
	public:
		static void log_packet(const AVFormatContext* fmt_ctx, const AVPacket* pkt, const std::string& name)
		{
			AVRational* time_base = &fmt_ctx->streams[pkt->stream_index]->time_base;

			char buffer[6][256] = { 0 };
			Log::print("pts:  " + std::string(av_ts2str(buffer[0], pkt->pts))
				+ " pts_time :" + av_ts2timestr(buffer[1], pkt->pts, time_base)
				+ " dts : " + av_ts2str(buffer[2], pkt->dts)
				+ " dts_time :" + av_ts2timestr(buffer[3], pkt->dts, time_base)
				+ " duration : " + av_ts2str(buffer[4], pkt->duration)
				+ " duration_time : " + av_ts2timestr(buffer[5], pkt->duration, time_base)
				+ " name : " + name);

		}
	};
	

	const int MAX_CACHE_SIZE = 10 * 1024 * 3;
	
	enum ENUM_MEDIA_TYPE
	{
		VIDEO = 1,
		AUDIO = 2
	};


	const std::string ENUM_STREAM_MPEGTS = "mpegts";
	const std::string ENUM_STREAM_FLV = "flv";

	class StreamPacket
	{
	public:
		StreamPacket(size_t len = 1)
		{
			p_data = new uint8_t[len];
		}

		StreamPacket(const uint8_t* data, const size_t& len) :m_len(len)
		{
			m_time = std::chrono::system_clock::now();
			p_data = new uint8_t[len];
			memcpy(p_data, data, len);
		}

		bool pushData(const uint8_t* data, const size_t& len)
		{
			// 总长度+新增的长度
			uint8_t* data_tmp = new uint8_t[m_len + len];
			// 先拷贝原来的数据
			memcpy(data_tmp, p_data, m_len);
			// 在拷贝新增的数据
			memcpy(data_tmp+ m_len, data, len);
			// 修正总长度
			m_len += len;
			// 释放老空间
			delete p_data;
			p_data = nullptr;
			// 将新空间交换给老空间
			p_data = data_tmp;
			return true;
		}

		~StreamPacket()
		{
			delete p_data;
			p_data = nullptr;
		}

		size_t getLen()
		{
			return m_len;
		}

		uint8_t* getData() 
		{
			return p_data;
		}

		std::chrono::system_clock::time_point getPacketTime()
		{
			return m_time;
		}
		
	private:
		uint8_t* p_data = nullptr;
		size_t m_len = 0;
		// 启动时间
		std::chrono::system_clock::time_point m_time;
	};
	
	class StreamParamBase
	{
	public:
		StreamParamBase(){}
		StreamParamBase(const std::string& m3u8_index,
			Buffer::RingBuffer<std::shared_ptr<StreamPacket> >* stream_mq):m_m3u8_index(m3u8_index),
			p_stream_mq(stream_mq) {}
		Buffer::RingBuffer<std::shared_ptr<StreamPacket> >* getMQ()const {return p_stream_mq;}
		std::string getIndex()const { return m_m3u8_index; }
	private:
		std::string m_m3u8_index;
		Buffer::RingBuffer<std::shared_ptr<StreamPacket> >* p_stream_mq = nullptr;
	};

	// hls设置参数
	class HLSParam : public StreamParamBase
	{
	public:
		HLSParam():StreamParamBase() {}
		HLSParam(
			const std::string & m3u8_index,
			const int & ts_time_mil,
			const int& ts_count,
			const int& ts_max,
			Buffer::RingBuffer<std::shared_ptr<StreamPacket> > *stream_mq):m_ts_time_mil(ts_time_mil),
			m_ts_count(ts_count),
			m_ts_count_index_max(ts_max), StreamParamBase(m3u8_index, stream_mq) {}
		~HLSParam(){}
		
		int getTSCount()const { return  m_ts_count; }
		int getTSIndexMax()const { return  m_ts_count_index_max; }
		int getTSTime()const { return m_ts_time_mil; }
		
	private:
		int m_ts_count_index_max = 1000;	// ts的最高上限是几个
		int m_ts_count = 3;			// ts的个数
		int m_ts_time_mil = 2*1000;			// 每个ts的时常,毫秒级
	};

	class FLVParam : public StreamParamBase
	{
	public:
		FLVParam() :StreamParamBase() {}
		FLVParam(const std::string &index,
			Buffer::RingBuffer<std::shared_ptr<StreamPacket> >* stream_mq):StreamParamBase(index,stream_mq){}
	private:
	};

	class HlsSerialize
	{
	public:
		HlsSerialize(
			const std::string& m3u8_path,
			const std::string& m3u8,
			const std::string& ts_path,
			uint8_t* ts_buffer,
			const size_t& len)
		{
			size_t data_len = sizeof(size_t) * 4 + m3u8.size()+ m3u8_path .size()+ ts_path.size() + len;
			// 初始化装数据的队列
			data = new uint8_t[data_len];
			
			size_t m3u8_len = m3u8.size();
			size_t ts_len = len;
			size_t m3u8_path_len = m3u8_path.size();
			size_t ts_path_len = ts_path.size();

			// 开头8个字节装m3u8 路由长度
			memcpy(data+total, (uint8_t*)&m3u8_path_len, sizeof(size_t));
			total += sizeof(size_t);
			memcpy(data + total, m3u8_path.data(), m3u8_path.size());
			total += m3u8_path.size();


			// 开头8个字节装m3u8长度
			memcpy(data+ total,(uint8_t*)&m3u8_len, sizeof(size_t));
			total += sizeof(size_t);
			memcpy(data + total, m3u8.data(), m3u8.size());
			total += m3u8.size();

			// 开头8个字节装ts路由长度
			memcpy(data + total, (uint8_t*)&ts_path_len, sizeof(size_t));
			total += sizeof(size_t);
			memcpy(data + total, ts_path.data(), ts_path.size());
			total += ts_path.size();


			//ts长度
			memcpy(data+ total, (uint8_t*)&ts_len, sizeof(size_t));
			total += sizeof(size_t);
			memcpy(data + total, ts_buffer, len);
			total += len;
		}
		~HlsSerialize()
		{
			delete data;
			data = nullptr;
		}

		

		std::shared_ptr<StreamPacket> getStreamPacket()
		{
			std::shared_ptr<StreamPacket> hls_paclet(new StreamPacket(data, total));
			return hls_paclet;
		}
	private:
		uint8_t* data = nullptr;
		size_t total = 0;
	};


	class FLVSerialize
	{
	public:
		FLVSerialize(
			std::shared_ptr<StreamPacket> flv_head,
			const std::string& flv_index,
			uint8_t* flv_buffer,
			const size_t& len)
		{
			// 3个flv的长度 + flv索引长度 + flv数据长度
			size_t data_len = sizeof(size_t) * 3 + flv_index.size() + len+ flv_head.get()->getLen();
			// 初始化装数据的队列
			data = new uint8_t[data_len];

			size_t flv_index_len = flv_index.size();
			size_t flv_len = len;
			size_t flv_head_len = flv_head.get()->getLen();

			// 封装头
			memcpy(data + total, (uint8_t*)&flv_head_len, sizeof(size_t));
			total += sizeof(size_t);
			memcpy(data + total, flv_head.get()->getData(), flv_head_len);
			total += flv_head_len;

			

			// 开头8个字节装flv 路由长度
			memcpy(data + total, (uint8_t*)&flv_index_len, sizeof(size_t));
			total += sizeof(size_t);
			memcpy(data + total, flv_index.data(), flv_index.size());
			total += flv_index.size();


			// 开头8个字节装m3u8长度
			memcpy(data + total, (uint8_t*)&flv_len, sizeof(size_t));
			total += sizeof(size_t);
			memcpy(data + total, flv_buffer, flv_len);
			total += flv_len;

		}
		~FLVSerialize()
		{
			delete data;
			data = nullptr;
		}



		std::shared_ptr<StreamPacket> getStreamPacket()
		{
			std::shared_ptr<StreamPacket> hls_paclet(new StreamPacket(data, total));
			return hls_paclet;
		}
	private:
		uint8_t* data = nullptr;
		size_t total = 0;
	};
}
